#define MSNETFRAME_C

#include <stdio.h>
#include <unistd.h> 
#include <sys/socket.h> 
#include <sys/types.h> 
#include <arpa/inet.h> 
#include <netinet/ip.h> 
//#include <netinet/tcp.h> 
#include <netinet/udp.h> 
#include <netinet/in.h> 
#include <net/if_arp.h> 
#include <netdb.h> 
#include <sys/ioctl.h> 
#include <sys/stat.h> 
#include <linux/if_packet.h>  
#include <errno.h>
#include <stdlib.h>
#include <string.h> 
#include <strings.h>
#include <unistd.h> 
#include <netdb.h> 
#include <sys/ioctl.h> 
#include <fcntl.h> 
#include <linux/if_ether.h>
#include <net/ethernet.h>

#include "mscommon.h"
#include "msnetwork.h"
#include "msnetframe.h"
#include "msstring.h"
#include <libmslog/mslog.h>

#define FLAG "NETFRAME"

#define DBG_FILTER_FRAME 	ms_false
#define DBG_FILTER 			ms_false
#define DBG_FILTER_IP 		ms_false
#define DBG_FILTER_MAC 		ms_false
#define TCPHEADER_LEN		(20/4)
static ms_void msframe_innerapi_printEthrtType(ms_bool ms_in debug,ms_u16 ms_in type ,ms_string str_type)
{
#define MS_CASE_ETHERTYPE(ether_type,des_string)	case ether_type:ms_enDbg(debug, "Type:%s",des_string);ms_strcpy(str_type, des_string);break;
	if( ms_range(type, 0x0000, 0x05DC)	){
		if( ms_range(type, 0x0101, 0x01FF)	){
			ms_enDbg(debug, "test" );
		}else{
			ms_enDbg(debug, "IEEE 802.3 len:%d", type );
		}
	}else{
		switch(type){
			MS_CASE_ETHERTYPE(ETHERTYPE_PUP, "Xerox PUP");		
			MS_CASE_ETHERTYPE(ETHERTYPE_SPRITE, "Sprite");	
			MS_CASE_ETHERTYPE(0x0600, "XEROX NS IDP");
			MS_CASE_ETHERTYPE(0x0661, "DLOG");
			MS_CASE_ETHERTYPE(ETHERTYPE_IP, "IPv4");
			MS_CASE_ETHERTYPE(0x0801, "X.75 Internet");
			MS_CASE_ETHERTYPE(0x0802, "NBS Internet");
			MS_CASE_ETHERTYPE(0x0803, "ECMA Internet");
			MS_CASE_ETHERTYPE(0x0804, "Chaosnet");
			MS_CASE_ETHERTYPE(0x0805, "X.25 Level 3");
			MS_CASE_ETHERTYPE(ETHERTYPE_ARP, "ARP");
			MS_CASE_ETHERTYPE(0x0808, "Frame Relay ARP");
			MS_CASE_ETHERTYPE(0x6559, "Raw Frame Relay");
			MS_CASE_ETHERTYPE(ETHERTYPE_REVARP, "DRARP");
			MS_CASE_ETHERTYPE(0x8037, "Novell Netware IPX");
			MS_CASE_ETHERTYPE(ETHERTYPE_AT, "AppleTalk protocol ");
			MS_CASE_ETHERTYPE(0x80D5, "IBM SNA Services over Ethernet");
			MS_CASE_ETHERTYPE(ETHERTYPE_AARP, "AppleTalk ARP");
			MS_CASE_ETHERTYPE(ETHERTYPE_VLAN, "IEEE 802.1Q VLAN tagging");
			MS_CASE_ETHERTYPE(ETHERTYPE_IPX, "IPX");
			MS_CASE_ETHERTYPE(0x814C, "SNMP");
			MS_CASE_ETHERTYPE(ETHERTYPE_IPV6, "IPv6");
			MS_CASE_ETHERTYPE(0x8809, "OAM");
			MS_CASE_ETHERTYPE(0x880B, "PPP");
			MS_CASE_ETHERTYPE(0x880C, "GSMP");
			MS_CASE_ETHERTYPE(0x8847, "MPLS <unicast>");
			MS_CASE_ETHERTYPE(0x8848, "MPLS<multicast>");
			MS_CASE_ETHERTYPE(0x8863, "PPPoE <Discovery Stage>");
			MS_CASE_ETHERTYPE(0x8864, "PPPoE <PPP Session Stage>");
			MS_CASE_ETHERTYPE(0x88BB, "LWAPP");
			MS_CASE_ETHERTYPE(0x88CC, "LLDP");
			MS_CASE_ETHERTYPE(0x8E88, "EAPOL");
			MS_CASE_ETHERTYPE(ETHERTYPE_LOOPBACK, "used to test interfaces");
			MS_CASE_ETHERTYPE(0x9100, "VLAN Tag Protocol Identifier1");
			MS_CASE_ETHERTYPE(0x9200, "VLAN Tag Protocol Identifier2");
			MS_CASE_ETHERTYPE(0xFFFF, "res");
			default:	
				ms_enDbg(debug,"Unknow ether type(%#x)",type);	
				break;
		}
	}
}
static ms_void msframe_innerapi_parseEthrt(ETHERContext *ms_out pether_ctt,struct ether_header * ms_in peth )
{
	ms_bufcheckDes(pether_ctt,"Param error####pether_ctt");
	ms_bufcheckDes(peth,"Param error####peth");
	
	FRAMEContext *pframe_ctt=&pether_ctt->frame_ctt;
	ms_mac2str( (char *)peth->ether_dhost, pframe_ctt->str_dest_mac);
	ms_mac2str( (char *)peth->ether_shost, pframe_ctt->str_source_mac);      
	
	msnet_api_macStr2Byte( pframe_ctt->str_dest_mac, pframe_ctt->dest_mac);
	msnet_api_macStr2Byte( pframe_ctt->str_source_mac, pframe_ctt->source_mac);
	pframe_ctt->type=ntohs( peth->ether_type );
	
	ms_enHlight(pether_ctt->debug, "============  FRAME  ============");
	ms_enDbg(pether_ctt->debug, "============  ether header info  ============");
	ms_enDbg(pether_ctt->debug, "Destination:%s", pframe_ctt->str_dest_mac);
	ms_enDbg(pether_ctt->debug, "Source:%s", pframe_ctt->str_source_mac);
	msframe_innerapi_printEthrtType( pether_ctt->debug,pframe_ctt->type , pframe_ctt->str_type);
}
static ms_void msframe_innerapi_parseIpv4( ETHERContext * ms_out pether_ctt,struct iphdr * ms_in iph )
{
#define MS_CASE_PROTO(protocol,des_string)	case protocol:	ms_enDbg(pether_ctt->debug, "Protocol:%s(%d)",des_string,protocol);ms_strcpy(pipheader_ctt->str_protocol, des_string);break;
	ms_bufcheckDes(pether_ctt,"Param error####pether_ctt");
	ms_bufcheckDes(iph,"Param error####iph");
	IPHEADERContext *pipheader_ctt=&pether_ctt->ethertype_data.ipheader_ctt;
	pipheader_ctt->version=iph->version;
	pipheader_ctt->header_len= iph->ihl;
	pipheader_ctt->tos= iph->tos;
	pipheader_ctt->total_len= ntohs(iph->tot_len);
	pipheader_ctt->id=ntohs(iph->id);
	pipheader_ctt->frag_offset=ntohs(iph->frag_off);
	//pipheader_ctt->flags;
	pipheader_ctt->ttl=iph->ttl;
	pipheader_ctt->protocol=iph->protocol;
	pipheader_ctt->checksum=ntohs(iph->check);
	pipheader_ctt->source_ip=iph->saddr;
	pipheader_ctt->dest_ip= iph->daddr;
	
	ms_enDbg(pether_ctt->debug, "=============== IP header info===============");
	ms_enDbg(pether_ctt->debug, "Version :%d", iph->version );
	ms_enDbg(pether_ctt->debug, "Header Length:%d bytes(%d)", iph->ihl * 4 , iph->ihl);
	ms_enDbg(pether_ctt->debug, "Differentiated Services Field: 0x%02x", iph->tos );
	ms_enDbg(pether_ctt->debug, "Total Length: %d", ntohs(iph->tot_len) );
	ms_enDbg(pether_ctt->debug, "Identification: 0x%04x(%d)", ntohs(iph->id) , ntohs(iph->id));
	//flags
	ms_enDbg(pether_ctt->debug, "Fragment offset: %d", ntohs(iph->frag_off) );
	ms_enDbg(pether_ctt->debug, "Time to live: %d", iph->ttl );
	switch (  iph->protocol )
	{
		MS_CASE_PROTO(IPPROTO_IP	,"Dummy protocol for TCP");
		MS_CASE_PROTO(IPPROTO_TCP	,"TCP");
		MS_CASE_PROTO(IPPROTO_UDP	,"UDP");
		MS_CASE_PROTO(IPPROTO_ICMP	, "ICMP");
		MS_CASE_PROTO(IPPROTO_IGMP	, "IGMP");
		MS_CASE_PROTO(IPPROTO_IPIP	, "IPIP tunnels");
		MS_CASE_PROTO(IPPROTO_EGP	, "EGP");
		MS_CASE_PROTO(IPPROTO_PUP	, "PUP");
		MS_CASE_PROTO(IPPROTO_IDP	, "IDP");
		MS_CASE_PROTO(IPPROTO_TP	, "TP");
		MS_CASE_PROTO(IPPROTO_DCCP	, "DCCP");
		MS_CASE_PROTO(IPPROTO_IPV6	, "IPV6");
		MS_CASE_PROTO(IPPROTO_RSVP	, "RSVP");
		MS_CASE_PROTO(IPPROTO_GRE	, "GRE ");
		MS_CASE_PROTO(IPPROTO_ESP	, "ESP ");
		MS_CASE_PROTO(IPPROTO_AH	, "AH ");
		MS_CASE_PROTO(IPPROTO_MTP	, "MTP");
		MS_CASE_PROTO(IPPROTO_BEETPH	, "BEETPH ");
		MS_CASE_PROTO(IPPROTO_ENCAP	, "ENCAP ");
		MS_CASE_PROTO(IPPROTO_PIM		, "PIM ");
		MS_CASE_PROTO(IPPROTO_COMP	, "COMP");
		MS_CASE_PROTO(IPPROTO_SCTP		, "SCTP ");
		MS_CASE_PROTO(IPPROTO_UDPLITE	, "UDPLITE ");
#ifndef OS_LINUX_X32	//armv7l
		MS_CASE_PROTO(IPPROTO_MPLS		, "MPLS ");
#endif
		default: 	ms_enDbg(pether_ctt->debug, "Unknow protocol(%d)", iph->protocol );
	}
	ms_enDbg(pether_ctt->debug, "Header checksum: %#x", ntohs(iph->check) );
	ms_enDbg(pether_ctt->debug, "Source : %s", inet_ntoa( *(struct in_addr *)(&iph->saddr)) );
	ms_enDbg(pether_ctt->debug, "Destination: %s", inet_ntoa( *(struct in_addr *)(&iph->daddr)) );	
}
static ms_void msframe_innerapi_parseTcpOpt( ETHERContext * ms_out pether_ctt,struct tcphdr * ms_in ptcp,ms_pbyte data  )
{
	ms_bufcheckDes(pether_ctt,"Param error####pether_ctt");
	ms_bufcheckDes(ptcp,"Param error####iph");
	ms_bufcheckDes(data,"Param error####iph");
	
	ms_string tcpopt_string[256]={"EOL","NOP","MSS","WSO","SACKP","SACK","ECHO","ECHOREPLY","TSOPT","POCP","POSP"};
	ms_u32 optlen=(ptcp->doff * 4) - 20;
	ms_enDbg(pether_ctt->debug,"====TCP Options:(%d bytes)", optlen );
	ms_pbyte ptcpopt_data=&(data[20]);
	TCPHEADEROPTIONContext *ptcpopt_ctt=&pether_ctt->ipprotocol_data.tcpheader_ctt.opt_ctt;
	TCPHEADEROption *ptcpheader_opt=ms_null;
	//ms_bufHex("tcp opt", &ptcpopt_data[0], optlen);
	ms_u32 index=0;
	for(index=0; (index<optlen && ptcpopt_ctt->tcpheader_opt_num <128);ptcpopt_ctt->tcpheader_opt_num++){
		ptcpheader_opt=&ptcpopt_ctt->tcpheader_opt[ptcpopt_ctt->tcpheader_opt_num];
		ptcpheader_opt->kind=ptcpopt_data[index];
		index+=1;
		switch(ptcpheader_opt->kind){
			case TCPOPT_KIND_EOL:
				ptcpheader_opt->len=0;
				ms_enDbg(pether_ctt->debug,"%s",tcpopt_string[ptcpheader_opt->kind]);
				break;
			case TCPOPT_KIND_NOP:
				ptcpheader_opt->len=0;
				ms_enDbg(pether_ctt->debug,"%s",tcpopt_string[ptcpheader_opt->kind]);
				break;
			case TCPOPT_KIND_MSS:
			case TCPOPT_KIND_WSO:
			case TCPOPT_KIND_SACKP:
			case TCPOPT_KIND_SACK:
			case TCPOPT_KIND_ECHO:
			case TCPOPT_KIND_ECHOREPLY:
			case TCPOPT_KIND_TSPOT:
			case TCPOPT_KIND_POCP:
			case TCPOPT_KIND_POSP:
			case TCPOPT_KIND_UTO:
				ptcpheader_opt->len=ptcpopt_data[index];
				index+=1;
				ms_memcpy(ptcpheader_opt->val, &ptcpopt_data[index], (ptcpheader_opt->len-2));
				index+=(ptcpheader_opt->len-2);
				ms_enDbg(pether_ctt->debug,"%s",tcpopt_string[ptcpheader_opt->kind]);
				switch(ptcpheader_opt->kind){
					case TCPOPT_KIND_MSS:
						ms_enDbg(pether_ctt->debug,"    -val:%u",ms_host_2b(ptcpheader_opt->val));
						break;
					case TCPOPT_KIND_WSO:
						ms_enDbg(pether_ctt->debug,"    -val:%u",ptcpheader_opt->val[0]);
						break;
					case TCPOPT_KIND_SACKP:
						ms_enDbg(pether_ctt->debug,"    -val:support sack");
						break;
					case TCPOPT_KIND_SACK:
						ms_enDbg(pether_ctt->debug,"    -len:%u",ptcpheader_opt->len);
						int sack_range_index=0;
						int sack_range_num=(ptcpheader_opt->len-2)/8;
						for(sack_range_index=0;sack_range_index<sack_range_num;sack_range_index++){
							ms_enDbg(pether_ctt->debug,"    -slre:%u~%u",
								ms_host_4b(&ptcpheader_opt->val[0+sack_range_index*8]),
								ms_host_4b(&ptcpheader_opt->val[4+sack_range_index*8])	);
						}
						break;
					case TCPOPT_KIND_TSPOT:
						ms_enDbg(pether_ctt->debug,"    -tsval:%u",ms_host_4b(&ptcpheader_opt->val[0]));
						ms_enDbg(pether_ctt->debug,"    -tsecr:%u",ms_host_4b(&ptcpheader_opt->val[4]));
						break;
					case TCPOPT_KIND_ECHO:
					case TCPOPT_KIND_ECHOREPLY:
					case TCPOPT_KIND_POCP:
					case TCPOPT_KIND_POSP:
						ms_enDbg(pether_ctt->debug,"    -val:unsupport parse");
						break;
				}

				if( TCPOPT_KIND_UTO==ptcpheader_opt->kind){
					ms_enDbg(pether_ctt->debug,"UTO");
					ms_enDbg(pether_ctt->debug,"    -G bit:%d",ptcpheader_opt->val[0]);
					if(1==ptcpheader_opt->val[0]){
						ms_enDbg(pether_ctt->debug,"    -UserTimeout:%d(minute)",ptcpheader_opt->val[1]);	
					}else{
						ms_enDbg(pether_ctt->debug,"    -UserTimeout:%d(s)",ptcpheader_opt->val[1]);
					}
				}
				break;
			default:
				ms_enDbg(pether_ctt->debug,"unknow kind:%d",ptcpheader_opt->kind);
				return;
				break;
		}
	}
}
static ms_void msframe_innerapi_parseTcp( ETHERContext * ms_out pether_ctt,struct tcphdr * ms_in ptcp,ms_pbyte ms_in data  )
{
	ms_bufcheckDes(pether_ctt,"Param error####pether_ctt");
	ms_bufcheckDes(ptcp,"Param error####iph");
	TCPHEADERContext *ptcpheader_ctt=&pether_ctt->ipprotocol_data.tcpheader_ctt;
	ptcpheader_ctt->source_port=ntohs( ptcp->source );
	ptcpheader_ctt->dest_port= ntohs( ptcp->dest );	
	ptcpheader_ctt->seq_num=ntohl( ptcp->seq ) ;	
	ptcpheader_ctt->ack_num=ntohl( ptcp->ack_seq )  ;	
	ptcpheader_ctt->header_len=ptcp->doff  ;		
	ptcpheader_ctt->urg=ptcp->urg  ;	
	ptcpheader_ctt->ack=ptcp->ack;	
	ptcpheader_ctt->psh=ptcp->psh;	
	ptcpheader_ctt->rst=ptcp->rst;	
	ptcpheader_ctt->syn=ptcp->syn;	
	ptcpheader_ctt->fin=ptcp->fin;	
	ptcpheader_ctt->win_size=ntohs( ptcp->window );	
	ptcpheader_ctt->check_sum=ntohs( ptcp->check );	
	ptcpheader_ctt->urgen_pointer=ntohs( ptcp->urg_ptr );	
	ms_enDbg(pether_ctt->debug, "==================== TCP Header Info =====================");
	ms_enDbg(pether_ctt->debug,"Source Port: %d", ntohs( ptcp->source ) );
	ms_enDbg(pether_ctt->debug,"Destination port:%d", ntohs( ptcp->dest ) );
	ms_enDbg(pether_ctt->debug,"Sequence_number :%u", ntohl( ptcp->seq ) );
	ms_enDbg(pether_ctt->debug,"Acknowledgment number:%u", ntohl( ptcp->ack_seq ) );
	ms_enDbg(pether_ctt->debug,"Header Length: %d bytes", ptcp->doff * 4 );
	ms_enDbg(pether_ctt->debug,"Flags: ");
	ms_enDbg(pether_ctt->debug,"    Urgent:%d", ptcp->urg);	
	ms_enDbg(pether_ctt->debug,"    Acknowledgment:%d", ptcp->ack);	
	ms_enDbg(pether_ctt->debug,"    Push :%d", ptcp->psh);
	ms_enDbg(pether_ctt->debug,"    Reset :%d", ptcp->rst );
	ms_enDbg(pether_ctt->debug,"    Syn :%d", ptcp->syn );
	ms_enDbg(pether_ctt->debug,"    Fin : %d", ptcp->fin );
	ms_enDbg(pether_ctt->debug,"Window size: %d", ntohs( ptcp->window ) );
	ms_enDbg(pether_ctt->debug,"Checksum: %d", ntohs( ptcp->check ) );
	ms_enDbg(pether_ctt->debug,"Urgent pointer: %d", ntohs( ptcp->urg_ptr ) );
         
	if( (ptcp->doff * 4) != 20 ){
		if((ptcp->doff * 4) <20){
			ms_error("Header Length(%d) is less than 20,maybe error",(ptcp->doff * 4));
		}else{
			if(ms_null!=data){
				msframe_innerapi_parseTcpOpt( pether_ctt, ptcp, data  );
			}
		}
	}
	IPHEADERContext *pipheader_ctt=&pether_ctt->ethertype_data.ipheader_ctt;
	ms_enDbg(pether_ctt->debug,"total_len len,ip_header_len,tcp_header_len: %d,%d,%d", 
		pipheader_ctt->total_len,pipheader_ctt->header_len,pether_ctt->ipprotocol_data.tcpheader_ctt.header_len);
	pether_ctt->data_len=pipheader_ctt->total_len-pipheader_ctt->header_len*4-pether_ctt->ipprotocol_data.tcpheader_ctt.header_len*4;
	ms_enDbg(pether_ctt->debug,"data len: %d", pether_ctt->data_len );
}
static ms_void msframe_innerapi_parseUdp( ETHERContext * ms_out pether_ctt,struct udphdr * ms_in pudp,ms_pbyte ms_in data  )
{
	ms_bufcheckDes(pether_ctt,"Param error####pether_ctt");
	ms_bufcheckDes(pudp,"Param error####iph");
	UDPHEADERContext *pudpheader_ctt=&pether_ctt->ipprotocol_data.udpheader_ctt;
	pudpheader_ctt->source_port=ntohs( pudp->source );
	pudpheader_ctt->dest_port= ntohs( pudp->dest );	
	pudpheader_ctt->len=ntohs( pudp->len ) ;	
	pudpheader_ctt->check_sum=ntohs( pudp->check )  ;	
	ms_enDbg(pether_ctt->debug, "==================== UDP Header Info =====================");
	ms_enDbg(pether_ctt->debug,"Source Port: %u", pudpheader_ctt->source_port );
	ms_enDbg(pether_ctt->debug,"Destination port:%u", pudpheader_ctt->dest_port );
	ms_enDbg(pether_ctt->debug,"len :%u", pudpheader_ctt->len );
	ms_enDbg(pether_ctt->debug,"Checksum:%#x", pudpheader_ctt->check_sum );
	pether_ctt->data_len=pudpheader_ctt->len-8;
	ms_enDbg(pether_ctt->debug,"data len: %d", pether_ctt->data_len );
	//ms_bufHex("Data", pether_ctt->data, pether_ctt->data_len);
}

static ms_void msframe_innerapi_parseArp( ETHERContext * ms_out pether_ctt,struct arphdr * ms_in parp )
{
	ms_bufcheckDes(pether_ctt,"Param error####pether_ctt");
	ms_bufcheckDes(parp,"Param error####parp");
	 ARPHEADERContext *parpheader_ctt=&pether_ctt->ethertype_data.arpheader_ctt;
	 parpheader_ctt->hardware_type=ntohs(parp->ar_hrd);
	 parpheader_ctt->protocol_type=ntohs(parp->ar_pro);
	parpheader_ctt->hardware_size= parp->ar_hln;
	parpheader_ctt->protocol_size= parp->ar_pln;
	parpheader_ctt->opcode= ntohs(parp->ar_op);


	ms_pu08 paddr = (char*)(parp + 1);
	
	ms_u08 sender_mac[18]={0};
	ms_u08 target_mac[18]={0};
	ms_mac2str( (ms_pu08)paddr, sender_mac);     
	msnet_api_macStr2Byte( sender_mac, parpheader_ctt->sender_mac);
	parpheader_ctt->sender_ipaddr=(inet_addr(inet_ntoa( *(struct in_addr *)(paddr+6) )));	
	ms_mac2str( (ms_pu08)(paddr+10), target_mac);  
	msnet_api_macStr2Byte( target_mac, parpheader_ctt->target_mac);
	parpheader_ctt->target_ipaddr=(inet_addr(inet_ntoa( *(struct in_addr *)(paddr+16) )));
	
	ms_enDbg(pether_ctt->debug, "==================== ARP Header Info =====================");
	switch( parpheader_ctt->hardware_type  ){
		case ARPHRD_ETHER:
			ms_enDbg(pether_ctt->debug,"hardware type: Ethernet 10/100Mbps.");  
			break;
		case ARPHRD_EETHER:
			ms_enDbg(pether_ctt->debug,"hardware type: Experimental Ethernet.");
			break;
		case ARPHRD_AX25:
			ms_enDbg(pether_ctt->debug,"hardware type: AX.25 Level 2.");
			break;
		case ARPHRD_PRONET:
			ms_enDbg(pether_ctt->debug,"hardware type: PROnet token ring.");
			break;
		case ARPHRD_IEEE802:
			ms_enDbg(pether_ctt->debug,"hardware type:IEEE 802.2 Ethernet/TR/TB.");
			break;
		case ARPHRD_APPLETLK:
			ms_enDbg(pether_ctt->debug,"hardware type:APPLEtalk.");
			break;
		case ARPHRD_ATM:   
			ms_enDbg(pether_ctt->debug,"hardware type:ATM.");                      
			break;
		case ARPHRD_IEEE1394:
			ms_enDbg(pether_ctt->debug,"hardware type:IEEE 1394 IPv4 .");
			break;
		default:
			ms_enDbg(pether_ctt->debug,"hardware type:Unknow.");
			break;
	}
	switch( parpheader_ctt->protocol_type  ){
		case ETHERTYPE_IP:
			ms_enDbg(pether_ctt->debug,"protocol type:IP");
			break;
		default:
			ms_enDbg(pether_ctt->debug,"protocol type:error.");
			break;
	}
	ms_enDbg(pether_ctt->debug,"hardware size: %d", parpheader_ctt->hardware_size);
	ms_enDbg(pether_ctt->debug,"protocol size: %d", parpheader_ctt->protocol_size);
	switch( parpheader_ctt->opcode ){
		case ARPOP_REQUEST:
			ms_enDbg(pether_ctt->debug,"opcode:requset");
			break;
		case ARPOP_REPLY:  
			ms_enDbg(pether_ctt->debug,"opcode:reply");
			break;
		default:
			ms_debug("opcode:unknow");
		break;
	}
	ms_enDbg(pether_ctt->debug,"sender mac: %s", sender_mac );
	ms_enDbg(pether_ctt->debug,"sender ipaddr:%s", inet_ntoa( *(struct in_addr *)(paddr+6) ));
	ms_enDbg(pether_ctt->debug,"target mac:%s", target_mac );
	ms_enDbg(pether_ctt->debug,"target ipaddr:%s", inet_ntoa( *(struct in_addr *)(paddr+16) ));
}
static ms_void msframe_innerapi_doUdp( ETHERContext * ms_out pether_ctt,ms_pbyte ms_in data )
{
	ms_bufcheckDes(pether_ctt,"Param error####pether_ctt");
	ms_bufcheckDes(data,"Param error####data");
	struct udphdr * pudp = ( struct udphdr * )data;
	msframe_innerapi_parseUdp(  pether_ctt,pudp ,data);
}
static ms_void msframe_innerapi_doTcp( ETHERContext * ms_out pether_ctt,ms_pbyte ms_in data )
{
	ms_bufcheckDes(pether_ctt,"Param error####pether_ctt");
	ms_bufcheckDes(data,"Param error####data");
	struct tcphdr * ptcp = ( struct tcphdr * )data;
	msframe_innerapi_parseTcp(  pether_ctt,ptcp ,data);
}
static ms_void msframe_innerapi_doIpv4( ETHERContext * ms_out pether_ctt,ms_pbyte ms_in data )
{
#define MS_CASE_IPV4_NOSPPORT(protocol,des_string)	case protocol:ms_enDbg(pether_ctt->debug,des_string ",no support parse");break;
	ms_bufcheckDes(pether_ctt,"Param error####pether_ctt");
	ms_bufcheckDes(data,"Param error####data");
	struct iphdr *pip= ( struct iphdr * ) data;    /* pip = point to ip layer */
	msframe_innerapi_parseIpv4( pether_ctt,pip );
	ms_pbyte pdata = data + pip->ihl * 4;
	struct tcphdr * ptcp=( struct tcphdr * )data;
	switch( pip->protocol ){
		case IPPROTO_TCP:
			msframe_innerapi_doTcp( pether_ctt,pdata );
			break;
		case IPPROTO_UDP:
			msframe_innerapi_doUdp( pether_ctt,pdata );
			break;

		MS_CASE_IPV4_NOSPPORT(IPPROTO_ICMP	, "ICMP");
		MS_CASE_IPV4_NOSPPORT(IPPROTO_IGMP	, "IGMP");
		MS_CASE_IPV4_NOSPPORT(IPPROTO_IPIP	, "IPIP tunnels");
		MS_CASE_IPV4_NOSPPORT(IPPROTO_EGP	, "EGP");
		MS_CASE_IPV4_NOSPPORT(IPPROTO_PUP	, "PUP");
		MS_CASE_IPV4_NOSPPORT(IPPROTO_IDP	, "IDP");
		MS_CASE_IPV4_NOSPPORT(IPPROTO_TP	, "TP");
		MS_CASE_IPV4_NOSPPORT(IPPROTO_DCCP	, "DCCP");
		MS_CASE_IPV4_NOSPPORT(IPPROTO_IPV6	, "IPV6");
		MS_CASE_IPV4_NOSPPORT(IPPROTO_RSVP	, "RSVP");
		MS_CASE_IPV4_NOSPPORT(IPPROTO_GRE	, "GRE ");
		MS_CASE_IPV4_NOSPPORT(IPPROTO_ESP	, "ESP ");
		MS_CASE_IPV4_NOSPPORT(IPPROTO_AH	, "AH ");
		MS_CASE_IPV4_NOSPPORT(IPPROTO_MTP		, "MTP");
		MS_CASE_IPV4_NOSPPORT(IPPROTO_BEETPH	, "BEETPH ");
		MS_CASE_IPV4_NOSPPORT(IPPROTO_ENCAP	, "ENCAP ");
		MS_CASE_IPV4_NOSPPORT(IPPROTO_PIM		, "PIM ");
		MS_CASE_IPV4_NOSPPORT(IPPROTO_COMP		, "COMP");
		MS_CASE_IPV4_NOSPPORT(IPPROTO_SCTP		, "SCTP ");
		MS_CASE_IPV4_NOSPPORT(IPPROTO_UDPLITE	, "UDPLITE ");
#ifndef OS_LINUX_X32	//armv7l
		MS_CASE_IPV4_NOSPPORT(IPPROTO_MPLS		, "MPLS ");
#endif
		default:
			ms_enDbg(pether_ctt->debug,"No supprt protocol(code:0x%02x(%d)),please fix me", pip->protocol, pip->protocol );
			break;
	}
}

static void msframe_innerapi_doIpv6( ETHERContext * ms_out pether_ctt,ms_pbyte ms_in data )
{
	ms_bufcheckDes(pether_ctt,"Param error####pether_ctt");
	ms_bufcheckDes(data,"Param error####data");
}

static void msframe_innerapi_doArp( ETHERContext * ms_out pether_ctt,ms_pbyte ms_in data )
{
	ms_bufcheckDes(pether_ctt,"Param error####pether_ctt");
	ms_bufcheckDes(data,"Param error####data");
	struct arphdr * parp= ( struct arphdr * ) data;
	msframe_innerapi_parseArp( pether_ctt,parp );
}
static ms_s32 msframe_innerapi_buildEthrt(ETHERContext *ms_out pether_ctt,ms_string str_dest_mac,
	ms_string str_source_mac ,ms_u16 type,ms_byte *outbuf )
{
	ms_bufcheckRetDes(0,pether_ctt,"Param error####pether_ctt");
	ms_bufcheckRetDes(0,str_source_mac,"Param error####str_source_mac");
	ms_bufcheckRetDes(0,outbuf,"Param error####outbuf");
	
	FRAMEContext *pframe_ctt=&pether_ctt->frame_ctt;
	msnet_api_macStr2Byte( str_dest_mac, pframe_ctt->dest_mac);
	msnet_api_macStr2Byte( str_source_mac, pframe_ctt->source_mac);
	pframe_ctt->type=type;
		
	ms_memcpy(outbuf, pframe_ctt->dest_mac,6);
	ms_memcpy(&outbuf[6], pframe_ctt->source_mac,6);
	ms_network_2b(&outbuf[12], pframe_ctt->type);

	msframe_innerapi_parseEthrt(pether_ctt,(struct ether_header *)outbuf);
	return 14;
}
static ms_s32 msframe_innerapi_buildLinuxCooked(ms_u16 type,ms_byte *outbuf )
{
	ms_s32 len=0;
	ms_network_2b(&outbuf[len], 0x0004);len+=2;
	ms_network_2b(&outbuf[len], 0x0200);len+=2;
	ms_network_2b(&outbuf[len], 0x0000);len+=2;
	ms_network_8b(&outbuf[len], 0x0000000000000000);len+=8;
	ms_network_2b(&outbuf[len], type);len+=2;
	return len;
}
static ms_void msframe_innerapi_buildIpv4(ms_bool flag_pppoe,ETHERContext *ms_out pether_ctt,
	ms_u08  protocol,ms_string source_ip,ms_string dest_ip ,
	ms_u32 exlen,
	ms_byte *outbuf )
{

	ms_bufcheckDes(pether_ctt,"Param error####pether_ctt");
	ms_bufcheckDes(source_ip,"Param error####source_ip");
	ms_bufcheckDes(dest_ip,"Param error####dest_ip");
	IPHEADERContext *pipheader_ctt=&pether_ctt->ethertype_data.ipheader_ctt;

	ms_u08  header_len=0;
	pipheader_ctt->version=0x4;
	switch(protocol){
		case IPPROTO_IGMP:
			header_len=24;
			if(flag_pppoe){
				pipheader_ctt->id=0x0000;
				pipheader_ctt->tos= 0xC0 ; 
				pipheader_ctt->flags=0x2 ; 
			}else{
				pipheader_ctt->id+=4961;
				pipheader_ctt->tos= 0x00; 
				pipheader_ctt->flags=0x00; 
			}
			pipheader_ctt->ttl=1;
			break;
		case IPPROTO_TCP:
			header_len=20;
			/*Fragment use:id,flags,frag_offset*/
			pipheader_ctt->id=0;
			pipheader_ctt->tos=0x00; 
			pipheader_ctt->flags=0x2;
			pipheader_ctt->ttl=64;
			break;
		case IPPROTO_UDP:
			header_len=20;
			exlen=8;
			pipheader_ctt->id+=4961;
			pipheader_ctt->tos=0x00; 
			pipheader_ctt->flags=0x2;
			pipheader_ctt->frag_offset=0;
			pipheader_ctt->ttl=64;
			break;

	}
	pipheader_ctt->header_len=(header_len/4);
	pipheader_ctt->checksum=0x0000;
	pipheader_ctt->protocol=protocol;		//tcp
	pipheader_ctt->source_ip=htonl(inet_addr(source_ip));
	pipheader_ctt->dest_ip=htonl(inet_addr(dest_ip));
	pipheader_ctt->total_len=(ms_u16) ((pipheader_ctt->header_len*4+exlen+pether_ctt->data_len)&0xffff);
         switch(protocol){
		case IPPROTO_IGMP:
			pipheader_ctt->router_alert_type	=0x94;
			pipheader_ctt->router_alert_len	=0x04;
			pipheader_ctt->router_alert		=0x0000;
			break;
		case IPPROTO_TCP:
			break;
	}
	
	outbuf[0]=pipheader_ctt->version<<4|pipheader_ctt->header_len;
	outbuf[1]=pipheader_ctt->tos;
	ms_network_2b(&(outbuf[2]), pipheader_ctt->total_len);
	ms_network_2b(&(outbuf[4]), pipheader_ctt->id);
	outbuf[6]=pipheader_ctt->flags<<5|(pipheader_ctt->frag_offset&0x1f00)>>8;
	outbuf[7]=pipheader_ctt->frag_offset&0xff;
	outbuf[8]=pipheader_ctt->ttl;
	outbuf[9]=pipheader_ctt->protocol;
	ms_network_2b(&(outbuf[10]), 00);
	ms_network_4b(&(outbuf[12]), pipheader_ctt->source_ip);
	ms_network_4b(&(outbuf[16]), pipheader_ctt->dest_ip);
         switch(protocol){
		case IPPROTO_IGMP:
			outbuf[20]=pipheader_ctt->router_alert_type;
			outbuf[21]=pipheader_ctt->router_alert_len;
			ms_network_2b(&(outbuf[22]), pipheader_ctt->router_alert);
			break;
		case IPPROTO_TCP:
			break;
	}
	pipheader_ctt->checksum=msnet_api_checksum((ms_u16 * )&outbuf[0], header_len);	 
	ms_network_2b(&(outbuf[10]), pipheader_ctt->checksum);
	msframe_innerapi_parseIpv4(pether_ctt, (struct iphdr * ms_in )outbuf);
         switch(protocol){
		case IPPROTO_IGMP:
			ms_enDbg(pether_ctt->debug, "router_alert_type: %u", (ms_u08)outbuf[20]);
			ms_enDbg(pether_ctt->debug, "router_alert_len: %u",  (ms_u08)outbuf[21]);
			ms_enDbg(pether_ctt->debug, "router_alert: %u", pipheader_ctt->router_alert);
			break;
		case IPPROTO_TCP:
			break;
	}
}


static ms_u32 msframe_innerapi_buildTcpOpt(MSBULDTCPContext *pmsbuildtcp_ctt,ms_byte *outbuf )
{
	ms_bufcheckRetDes(0,pmsbuildtcp_ctt,"Param error####pmsbuildtcp_ctt");
	ms_string tcpopt_string[256]={"EOL","NOP","MSS","WSO","SACKP","SACK","ECHO","ECHOREPLY","TSOPT","POCP","POSP"};
	ms_u32 index=0;
	ms_u32 len_tcpheader_opt=0;
	for(index=0;index <pmsbuildtcp_ctt->opt_ctt.tcpheader_opt_num;index++){
		TCPHEADEROption* ptcpheader_opt=&pmsbuildtcp_ctt->opt_ctt.tcpheader_opt[index];
		switch(ptcpheader_opt->kind){
			case TCPOPT_KIND_EOL:
				outbuf[len_tcpheader_opt]=ptcpheader_opt->kind;
				len_tcpheader_opt+=1;
				break;
			case TCPOPT_KIND_NOP:
				outbuf[len_tcpheader_opt]=ptcpheader_opt->kind;
				len_tcpheader_opt+=1;
				break;
			case TCPOPT_KIND_MSS:
			case TCPOPT_KIND_WSO:
			case TCPOPT_KIND_SACKP:
			case TCPOPT_KIND_SACK:
			case TCPOPT_KIND_ECHO:
			case TCPOPT_KIND_ECHOREPLY:
			case TCPOPT_KIND_TSPOT:
			case TCPOPT_KIND_POCP:
			case TCPOPT_KIND_POSP:
			case TCPOPT_KIND_UTO:
				outbuf[len_tcpheader_opt]=ptcpheader_opt->kind;
				len_tcpheader_opt+=1;
				outbuf[len_tcpheader_opt]=ptcpheader_opt->len;
				len_tcpheader_opt+=1;
				ms_memcpy(&outbuf[len_tcpheader_opt], ptcpheader_opt->val, (ptcpheader_opt->len-2));
				len_tcpheader_opt+=(ptcpheader_opt->len-2);
				break;
			default:
				break;
		}
	}
	return len_tcpheader_opt;
}
static ms_void msframe_innerapi_buildTcpPayload(ETHERContext *ms_out pether_ctt,
	MSBULDTCPContext *pmsbuildtcp_ctt,ms_byte *outbuf )
{
	ms_bufcheckDes(pether_ctt,"Param error####pether_ctt");
	IPHEADERContext *pipheader_ctt=&pether_ctt->ethertype_data.ipheader_ctt;
	TCPHEADERContext *ptcpheader_ctt=&pether_ctt->ipprotocol_data.tcpheader_ctt;
	ptcpheader_ctt->source_port=pmsbuildtcp_ctt->source_port;
	ptcpheader_ctt->dest_port=pmsbuildtcp_ctt->dest_port;
	ptcpheader_ctt->seq_num=pmsbuildtcp_ctt->seq_num;
	ptcpheader_ctt->ack_num=pmsbuildtcp_ctt->ack_num;
	ptcpheader_ctt->win_size=64240;
	ptcpheader_ctt->check_sum=0x0000;	
	ptcpheader_ctt->urgen_pointer=0x0000;
	ptcpheader_ctt->header_len=TCPHEADER_LEN+ (pmsbuildtcp_ctt->opt_ctt.tcpheader_opt_len/4);
ms_debug("-----ptcpheader_ctt->header_len:%d",ptcpheader_ctt->header_len);	
	ptcpheader_ctt->urg=pmsbuildtcp_ctt->urg;
	ptcpheader_ctt->ack=pmsbuildtcp_ctt->ack;
	ptcpheader_ctt->psh=pmsbuildtcp_ctt->psh;
	ptcpheader_ctt->rst=pmsbuildtcp_ctt->rst;
	ptcpheader_ctt->syn=pmsbuildtcp_ctt->syn;
	ptcpheader_ctt->fin=pmsbuildtcp_ctt->fin;

	ms_network_2b(&(outbuf[0]), ptcpheader_ctt->source_port);
	ms_network_2b(&(outbuf[2]), ptcpheader_ctt->dest_port);
	ms_network_4b(&(outbuf[4]), ptcpheader_ctt->seq_num);
	ms_network_4b(&(outbuf[8]), ptcpheader_ctt->ack_num);
	outbuf[12]=ptcpheader_ctt->header_len<<4|(ptcpheader_ctt->res&0x3c)>>2;	
	outbuf[13]=(ptcpheader_ctt->res&0x3)<<6|ptcpheader_ctt->urg<<5|ptcpheader_ctt->ack<<4|ptcpheader_ctt->psh<<3 \
		|ptcpheader_ctt->rst<<2|ptcpheader_ctt->syn<<1|ptcpheader_ctt->fin;	
	ms_network_2b(&(outbuf[14]), ptcpheader_ctt->win_size);
	ms_network_2b(&(outbuf[16]), ptcpheader_ctt->check_sum);
	ms_network_2b(&(outbuf[18]), ptcpheader_ctt->urgen_pointer);

	ms_u32 len_tcpheader_opt=msframe_innerapi_buildTcpOpt(pmsbuildtcp_ctt,&(outbuf[20] ));
		
	ptcpheader_ctt->check_sum=msframe_api_tcpChecksum(pether_ctt,(ms_pbyte)&outbuf[0]);	
	ms_network_2b(&(outbuf[16]), ptcpheader_ctt->check_sum);
	msframe_innerapi_parseTcp(pether_ctt, (struct tcphdr * ms_in )outbuf,ms_null);
}
static ms_void msframe_innerapi_buildUdpPayload(ETHERContext *ms_out pether_ctt,
	MSBULDUDPContext *pPUdp_ctt,ms_byte *outbuf)
{
	ms_bufcheckDes(pether_ctt,"Param error####pether_ctt");
	IPHEADERContext *pipheader_ctt=&pether_ctt->ethertype_data.ipheader_ctt;
	UDPHEADERContext *pHUdp_ctt=&pether_ctt->ipprotocol_data.udpheader_ctt;
	pHUdp_ctt->source_port=pPUdp_ctt->srcPort;
	pHUdp_ctt->dest_port=pPUdp_ctt->destPort;
	pHUdp_ctt->len=8+pether_ctt->data_len;
	pHUdp_ctt->check_sum=0;
	ms_network_2b(&(outbuf[0]), pHUdp_ctt->source_port);
	ms_network_2b(&(outbuf[2]), pHUdp_ctt->dest_port);
	ms_network_2b(&(outbuf[4]), pHUdp_ctt->len);
	ms_network_2b(&(outbuf[6]), pHUdp_ctt->check_sum);
	pHUdp_ctt->check_sum=msframe_api_udpChecksum(pether_ctt,(ms_pbyte)&outbuf[0]);
	ms_network_2b(&(outbuf[6]), pHUdp_ctt->check_sum);
	msframe_innerapi_parseUdp(pether_ctt, (struct udphdr * ms_in )outbuf,ms_null);
}

static ms_u32 msframe_innerapi_getIgmpData1(ETHERContext *ms_out pether_ctt,IGMPHEADERContext *pigmp_ctt,ms_byte *outbuf)
{
	ms_u16 datalen=0;
	
	outbuf[datalen]=pigmp_ctt->type;
	datalen+=1;
	outbuf[datalen]=pigmp_ctt->max_resp_time;
	datalen+=1;
	ms_u16 offset_checksum=datalen;
	ms_network_2b(&outbuf[datalen], pigmp_ctt->check_sum);
	datalen+=2;
	ms_network_4b(&outbuf[datalen], pigmp_ctt->multicast_addr);
	datalen+=4;
	pigmp_ctt->check_sum= msnet_api_checksum((ms_u16 * )&outbuf[0],datalen);
	ms_network_2b(&outbuf[offset_checksum], pigmp_ctt->check_sum);
	
	ms_enDbg(pether_ctt->debug, "=============== IGMP data info(datalen:%d)===============",datalen);
	ms_enDbg(pether_ctt->debug, "type :0x%02x", pigmp_ctt->type );
	ms_enDbg(pether_ctt->debug, "Max Resp Time:%d sec",pigmp_ctt->max_resp_time);
	ms_enDbg(pether_ctt->debug, "Checksum:0x%04x", pigmp_ctt->check_sum);
	ms_u32  multicast_addr=htonl(pigmp_ctt->multicast_addr);
	ms_enDbg(pether_ctt->debug, "Multicast Addr:%s", inet_ntoa( *(struct in_addr *)(&multicast_addr)) );	
	return datalen;
}
static ms_u32 msframe_innerapi_getIgmpData2(ETHERContext *ms_out pether_ctt,IGMPHEADERContext *pigmp_ctt,ms_byte *outbuf)
{
	ms_u16 datalen=0;
	outbuf[datalen]=pigmp_ctt->type;
	datalen+=1;
	outbuf[datalen]=0x00;
	datalen+=1;
	ms_u16 offset_checksum=datalen;
	ms_network_2b(&outbuf[datalen], pigmp_ctt->check_sum);
	datalen+=2;
	ms_network_2b(&outbuf[datalen], pigmp_ctt->res);
	datalen+=2;
	ms_network_2b(&outbuf[datalen], pigmp_ctt->num_group_records);
	datalen+=2;
	outbuf[datalen]=pigmp_ctt->record_type;
	datalen+=1;
	outbuf[datalen]=pigmp_ctt->aux_data;
	datalen+=1;
	ms_network_2b(&outbuf[datalen], pigmp_ctt->num_src);
	datalen+=2;
	ms_network_4b(&outbuf[datalen], pigmp_ctt->multicast_addr);
	datalen+=4;
	ms_u16 index=0;
	for(index=0;index<pigmp_ctt->num_src;index++){
		ms_network_4b(&outbuf[datalen], pigmp_ctt->source_addr[index]);
		datalen+=4;
	}
	pigmp_ctt->check_sum= msnet_api_checksum((ms_u16 * )&outbuf[0],datalen);
	ms_network_2b(&outbuf[offset_checksum], pigmp_ctt->check_sum);
	
	ms_enDbg(pether_ctt->debug, "=============== IGMP data info(datalen:%d)===============",datalen);
	ms_enDbg(pether_ctt->debug, "type :0x%02x", pigmp_ctt->type );
	ms_enDbg(pether_ctt->debug, "Reserved :%05d", 0 );
	ms_enDbg(pether_ctt->debug, "Checksum:0x%04x", pigmp_ctt->check_sum);
	ms_enDbg(pether_ctt->debug, "Reserved :%04d", pigmp_ctt->res );
	ms_enDbg(pether_ctt->debug, "Num Group Records :%d", pigmp_ctt->num_group_records );
	ms_enDbg(pether_ctt->debug, "Record Type:%d sec",pigmp_ctt->record_type);
	ms_enDbg(pether_ctt->debug, "Rux Data:%d sec",pigmp_ctt->aux_data);
	ms_enDbg(pether_ctt->debug, "Num Src:%d sec",pigmp_ctt->num_src);
	ms_u32  multicast_addr=htonl(pigmp_ctt->multicast_addr);
	ms_enDbg(pether_ctt->debug, "Multicast Addr:%s", inet_ntoa( *(struct in_addr *)(&multicast_addr)) );	
	return datalen;
}
static ms_u08 msframe_innerapi_getIgmpRecordType(MSBULDIGMPContext *pigmp_ctt_in)
{
#define CHANGE_TO_INCLUDE_MODE	0x03
#define CHANGE_TO_EXCLUDE_MODE	0x04
#define ALLOW_NEW_SOURCE			0x05
#define BLOCK_OLD_SOURCE			0x06
	ms_u08 record_type=0;
	switch(pigmp_ctt_in->igmp_cmd){
		case IGMP_CMD_REPORT:
			if(IGMP_VERSION_3==pigmp_ctt_in->igmp_ver){
				if(ms_true ==pigmp_ctt_in->flag_include){
					record_type=ALLOW_NEW_SOURCE;
				}else{
					record_type=CHANGE_TO_EXCLUDE_MODE;
				}
			}
			break;
		case IGMP_CMD_LEAVE_GROUP:
			if(IGMP_VERSION_3==pigmp_ctt_in->igmp_ver){
				if(ms_true ==pigmp_ctt_in->flag_include){
					record_type=BLOCK_OLD_SOURCE;
				}else{
					record_type=CHANGE_TO_INCLUDE_MODE;
				}
			}
			break;
	}
	return record_type;
}
static ms_u08 msframe_innerapi_getIgmpType(MSBULDIGMPContext *pigmp_ctt_in)
{
#define IGMP_MEMBERSHIP_QUERY   		0x11	
#define IGMP_V1_MEMBERSHIP_REPORT		0x12	
#define IGMP_V2_MEMBERSHIP_REPORT		0x16	
#define IGMP_V2_LEAVE_GROUP			0x17	
#define IGMP_V3_MEMBERSHIP_REPORT		0x22
	ms_u08 type=0;
	switch(pigmp_ctt_in->igmp_cmd){
		case IGMP_CMD_QUERY:
			type=IGMP_MEMBERSHIP_QUERY;
			break;
		case IGMP_CMD_REPORT:
			switch(pigmp_ctt_in->igmp_ver){
				case IGMP_VERSION_1:
					type=IGMP_V1_MEMBERSHIP_REPORT;
					break;
				case IGMP_VERSION_2:
					type=IGMP_V2_MEMBERSHIP_REPORT;
					break;
				case IGMP_VERSION_3:
					type=IGMP_V3_MEMBERSHIP_REPORT;
					break;
			}
			break;
		case IGMP_CMD_LEAVE_GROUP:
			switch(pigmp_ctt_in->igmp_ver){
				case IGMP_VERSION_1:
					break;
				case IGMP_VERSION_2:
					type=IGMP_V2_LEAVE_GROUP;
					break;
				case IGMP_VERSION_3:
					type=IGMP_V3_MEMBERSHIP_REPORT;
					break;
			}
			break;
	}
	return type;
}
static ms_u32 msframe_innerapi_buildIgmp(ETHERContext *ms_out pether_ctt,
	MSBULDIGMPContext *pigmp_ctt_in,ms_byte *outbuf )
{
	#define IGMPV3_REPORT_ADDRESS			0xe0000016
	IGMPHEADERContext *pigmp_ctt=&pether_ctt->ipprotocol_data.igmpheader_ctt;
	pigmp_ctt->type=msframe_innerapi_getIgmpType(pigmp_ctt_in);
	pigmp_ctt->max_resp_time=0;
	pigmp_ctt->check_sum=0x00;
	pigmp_ctt->res=0x00;
	pigmp_ctt->num_group_records=0x01;
	pigmp_ctt->record_type=msframe_innerapi_getIgmpRecordType(pigmp_ctt_in);	
	pigmp_ctt->aux_data=0x00;	
	pigmp_ctt->num_src=pigmp_ctt_in->num_src;	
	pigmp_ctt->multicast_addr=htonl(inet_addr(pigmp_ctt_in->dest_ip));
	ms_u16 index=0;
	for(index=0;index<pigmp_ctt->num_src;index++){
		ms_string source_addr_string=pigmp_ctt_in->source_addr[index];
		pigmp_ctt->source_addr[index]=htonl(inet_addr(source_addr_string));
	}
	
	ms_u32 len=0;
	switch(pigmp_ctt_in->igmp_cmd){
		case IGMP_CMD_QUERY:
			len=msframe_innerapi_getIgmpData1( pether_ctt,pigmp_ctt,  outbuf);
			break;
		case IGMP_CMD_REPORT:
		case IGMP_CMD_LEAVE_GROUP:
			switch(pigmp_ctt_in->igmp_ver){
				case IGMP_VERSION_1:
				case IGMP_VERSION_2:
					len=msframe_innerapi_getIgmpData1( pether_ctt,pigmp_ctt,  outbuf);
					break;
				case IGMP_VERSION_3:
					len=msframe_innerapi_getIgmpData2( pether_ctt,pigmp_ctt,  outbuf);
					break;
			}
			break;
	}
	return len;
}
ms_bool msframe_innerapi_filterFrameByMac( ms_string strdes,MSFRAMEFILTERConfig*pmsframefilter_config)
{
	MSFRAMEFILTERContext *pmsframefilter_ctt=&pmsframefilter_config->msframefilter_ctt;
	ETHERContext *pether_ctt=&pmsframefilter_ctt->ether_ctt;
	FRAMEContext *pframe_ctt=&pether_ctt->frame_ctt;
	//如果设置了MAC过滤，则只要源或目的MAC满足，都进行过滤
	if(ms_true==pmsframefilter_ctt->flag_filter_mac){
		if(ms_false==msstr_api_isCasestr( pmsframefilter_config->filter_mac,pether_ctt->frame_ctt.str_source_mac)
			&&ms_false==msstr_api_isCasestr( pmsframefilter_config->filter_mac,pether_ctt->frame_ctt.str_dest_mac)){
			return ms_false;
		}else{
			ms_enDbg(DBG_FILTER_MAC,"[%s]filter_mac:%s ,source_mac,dest_mac:%s.%s", strdes,pmsframefilter_config->filter_mac,pether_ctt->frame_ctt.str_source_mac,pether_ctt->frame_ctt.str_dest_mac);
		}
	}else{
	//严格按照源或目的MAC进行过滤
		if((ms_true==pmsframefilter_ctt->flag_filter_mac_source
				&&(ms_false==msstr_api_isCasestr(pmsframefilter_config->filter_mac_source,pether_ctt->frame_ctt.str_source_mac )))
			||(ms_true==pmsframefilter_ctt->flag_filter_mac_dest
				&&(ms_false==msstr_api_isCasestr(pmsframefilter_config->filter_mac_dest,pether_ctt->frame_ctt.str_dest_mac)))
		){
			return ms_false;
		}
	}
	return ms_true;
}
ms_bool msframe_innerapi_filterFrameByEtherInfo( ms_string strdes,MSFRAMEFILTERConfig*pmsframefilter_config)
{
	MSFRAMEFILTERContext *pmsframefilter_ctt=&pmsframefilter_config->msframefilter_ctt;

	ETHERContext *pether_ctt=&pmsframefilter_ctt->ether_ctt;
	if( ETHERTYPE_IP!=pether_ctt->frame_ctt.type ){
		return ms_false;
	}
	ms_enDbg(DBG_FILTER_IP,"[%s]filter_ip",strdes);
//协议过滤	
	IPHEADERContext *ipheader_ctt=&pether_ctt->ethertype_data.ipheader_ctt;
	if((ms_true==pmsframefilter_ctt->flag_filter_protocol)
		&&(pmsframefilter_ctt->filter_protocol!=ipheader_ctt->protocol)){
		return ms_false;
	}
//filter_ip		
	ms_byte  source_ip[32]={0};
	ms_byte  dest_ip[32]={0};
	ms_sprintfs(source_ip, "%s", inet_ntoa( *(struct in_addr *)(&ipheader_ctt->source_ip)));
	ms_sprintfs(dest_ip	   , "%s", inet_ntoa( *(struct in_addr *)(&ipheader_ctt->dest_ip)));
	if(ms_true==pmsframefilter_ctt->flag_filter_ip){
		if(ms_false==msstr_api_isCasestr(pmsframefilter_config->filter_ip,source_ip )
			&&ms_false==msstr_api_isCasestr(pmsframefilter_config->filter_ip,dest_ip )){
			return ms_false;
		}
	}else{
		if(((ms_true==pmsframefilter_ctt->flag_filter_ip_source)&&ms_false==msstr_api_isCasestr(pmsframefilter_config->filter_ip_source,source_ip ))
			||(	(ms_true==pmsframefilter_ctt->flag_filter_ip_dest)&&ms_false==msstr_api_isCasestr(pmsframefilter_config->filter_ip_dest,dest_ip )) 
		){
				return ms_false;
		}
	}
//filter_port	
	if(ms_true==pmsframefilter_ctt->flag_filter_port
		||ms_true==pmsframefilter_ctt->flag_filter_port_source
		||ms_true==pmsframefilter_ctt->flag_filter_port_dest
	){
		ms_s32  source_port=-1;
		ms_s32  dest_port=-1;
		TCPHEADERContext *ptcpheader_ctt=&pether_ctt->ipprotocol_data.tcpheader_ctt;
		UDPHEADERContext *pudpheader_ctt=&pether_ctt->ipprotocol_data.udpheader_ctt;
		switch(ipheader_ctt->protocol){
			case IPPROTO_TCP:
				source_port=ptcpheader_ctt->source_port ;
				dest_port= ptcpheader_ctt->dest_port ;
				break;
			case IPPROTO_UDP:
				source_port=pudpheader_ctt->source_port ;
				dest_port= pudpheader_ctt->dest_port ;
				break;
		}

		if(ms_true==pmsframefilter_ctt->flag_filter_port){
			if((pmsframefilter_config->filter_port!=source_port)
				&&(pmsframefilter_config->filter_port!=dest_port)){
				return ms_false;
			}
		}else{
			if(((ms_true==pmsframefilter_ctt->flag_filter_port_source)&&(pmsframefilter_config->filter_port_source!=source_port))
				||(	(ms_true==pmsframefilter_ctt->flag_filter_port_dest)&&(pmsframefilter_config->filter_port_dest!=dest_port)) 
			){
				return ms_false;
			}
		}
	}
	return ms_true;
}
ms_s08 msframe_api_doFrame( ETHERContext * ms_out pether_ctt,ms_pbyte ms_in frame_buf ,ms_bool flag_parseEtherInfo)
{
#define MS_CASE_ETHERTYPE_NOSPPORT(ether_type,des_string)	case ether_type:ms_enDbg(pether_ctt->debug,des_string ", no support to parse this frame");break;
#define MS_CASE_ETHERTYPE_NOSPPORT_NOSTR(ether_type)	case ether_type:break;
	ms_bufcheckRetDes(-1,pether_ctt,"Param error####pether_ctt");
	ms_bufcheckRetDes(-1,frame_buf,"Param error####frame_buf");
	struct ether_header * peth= (struct ether_header *)frame_buf;
	msframe_innerapi_parseEthrt( pether_ctt,peth );
	//无需解析ether_type，则直接返回。加快处理速度
	if(ms_false==flag_parseEtherInfo){
		return 0;
	}
	ms_pbyte pdata= frame_buf + sizeof( struct ether_header );
	ms_s08 ret=0;
	switch( ntohs( peth->ether_type ) ){
		case ETHERTYPE_IP:
			msframe_innerapi_doIpv4( pether_ctt,pdata );
			break;
		case ETHERTYPE_ARP:
			msframe_innerapi_doArp( pether_ctt,pdata );
			break;
		MS_CASE_ETHERTYPE_NOSPPORT(ETHERTYPE_PUP, " Xerox PUP");		
		MS_CASE_ETHERTYPE_NOSPPORT(ETHERTYPE_SPRITE, " Sprite");	
		MS_CASE_ETHERTYPE_NOSPPORT(0x0600, "XEROX NS IDP");
		MS_CASE_ETHERTYPE_NOSPPORT(0x0661, "DLOG");
		MS_CASE_ETHERTYPE_NOSPPORT(0x0801, "X.75 Internet");
		MS_CASE_ETHERTYPE_NOSPPORT(0x0802, "NBS Internet");
		MS_CASE_ETHERTYPE_NOSPPORT(0x0803, "ECMA Internet");
		MS_CASE_ETHERTYPE_NOSPPORT(0x0804, "Chaosnet");
		MS_CASE_ETHERTYPE_NOSPPORT(0x0805, "X.25 Level 3");
		MS_CASE_ETHERTYPE_NOSPPORT(0x0808, "ARP");
		MS_CASE_ETHERTYPE_NOSPPORT(0x6559, "Raw Frame Relay");
		MS_CASE_ETHERTYPE_NOSPPORT(0x8037, "Novell Netware IPX");
		MS_CASE_ETHERTYPE_NOSPPORT(ETHERTYPE_AT, "AppleTalk protocol ");
		MS_CASE_ETHERTYPE_NOSPPORT(0x80D5, "IBM SNA Services over Ethernet");
		MS_CASE_ETHERTYPE_NOSPPORT(ETHERTYPE_AARP, "AppleTalk ARP");
		MS_CASE_ETHERTYPE_NOSPPORT(ETHERTYPE_VLAN, "IEEE 802.1Q VLAN tagging");  ///
		MS_CASE_ETHERTYPE_NOSPPORT(ETHERTYPE_IPX, "IPX");
		MS_CASE_ETHERTYPE_NOSPPORT(0x814C, "SNMP");
		MS_CASE_ETHERTYPE_NOSPPORT_NOSTR(ETHERTYPE_IPV6);
		MS_CASE_ETHERTYPE_NOSPPORT(0x8809, "OAM");
		MS_CASE_ETHERTYPE_NOSPPORT(0x880B, "PPP");
		MS_CASE_ETHERTYPE_NOSPPORT(0x880C, "GSMP");
		MS_CASE_ETHERTYPE_NOSPPORT(0x8847, "MPLS <unicast>");
		MS_CASE_ETHERTYPE_NOSPPORT(0x8848, "MPLS<multicast>");
		MS_CASE_ETHERTYPE_NOSPPORT(0x8863, "PPPoE <Discovery Stage>");
		MS_CASE_ETHERTYPE_NOSPPORT(0x8864, "PPPoE <PPP Session Stage>");
		MS_CASE_ETHERTYPE_NOSPPORT(0x88BB, "LWAPP");
		MS_CASE_ETHERTYPE_NOSPPORT(0x88CC, "LLDP");
		MS_CASE_ETHERTYPE_NOSPPORT(0x8E88, "EAPOL");
		MS_CASE_ETHERTYPE_NOSPPORT(ETHERTYPE_LOOPBACK, "used to test interfaces");
		MS_CASE_ETHERTYPE_NOSPPORT(0x9100, "VLAN Tag Protocol Identifier1");
		MS_CASE_ETHERTYPE_NOSPPORT(0x9200, "VLAN Tag Protocol Identifier2");
		MS_CASE_ETHERTYPE_NOSPPORT(0xFFFF, "res");
		defalut:
			ret=-1;
			ms_enDbg(pether_ctt->debug,"No supprt ether_type(0x%04x)", ntohs( peth->ether_type ) );
			break;
	}
	return ret;
}
ms_bool msframe_api_isFilterMac( MSFRAMEFILTERContext *pmsframefilter_ctt)
{
	return (ms_true==pmsframefilter_ctt->flag_filter_mac
		||ms_true==pmsframefilter_ctt->flag_filter_mac_source
		||ms_true==pmsframefilter_ctt->flag_filter_mac_dest) ? ms_true : ms_false;
}
ms_bool msframe_api_isFilterEtherInfo( MSFRAMEFILTERContext *pmsframefilter_ctt)
{
	return (ms_true==pmsframefilter_ctt->flag_filter_protocol
			||ms_true==pmsframefilter_ctt->flag_filter_ip
			||ms_true==pmsframefilter_ctt->flag_filter_ip_source
			||ms_true==pmsframefilter_ctt->flag_filter_ip_dest
			||ms_true==pmsframefilter_ctt->flag_filter_port
			||ms_true==pmsframefilter_ctt->flag_filter_port_source
			||ms_true==pmsframefilter_ctt->flag_filter_port_dest) ? ms_true : ms_false;
}
ms_bool msframe_api_filterFrame( ms_string strdes,ms_pbyte ms_in frame_buf,MSFRAMEFILTERConfig*pmsframefilter_config)
{
	MSFRAMEFILTERContext *pmsframefilter_ctt=&pmsframefilter_config->msframefilter_ctt;
	if(ms_false==pmsframefilter_ctt->flag_init){
//根据MAC进行过滤
		pmsframefilter_ctt->flag_filter_mac		=ms_bufUnvalid(pmsframefilter_config->filter_mac) 		? ms_false : ms_true;
		pmsframefilter_ctt->flag_filter_mac_source	=ms_bufUnvalid(pmsframefilter_config->filter_mac_source) ? ms_false : ms_true;
		pmsframefilter_ctt->flag_filter_mac_dest	=ms_bufUnvalid(pmsframefilter_config->filter_mac_dest) 	 ? ms_false : ms_true;
//根据协议进行过滤
		if(ms_bufUnvalid(pmsframefilter_config->filter_protocol)){
			pmsframefilter_ctt->flag_filter_protocol=ms_false;
		}else if(ms_strncmp_saeq(pmsframefilter_config->filter_protocol, "udp")){
			pmsframefilter_ctt->filter_protocol=IPPROTO_UDP;
			pmsframefilter_ctt->flag_filter_protocol=ms_true;
		}else if(ms_strncmp_saeq(pmsframefilter_config->filter_protocol, "tcp")){
			pmsframefilter_ctt->filter_protocol=IPPROTO_TCP;
			pmsframefilter_ctt->flag_filter_protocol=ms_true;
		}else{
			pmsframefilter_ctt->flag_filter_protocol=ms_false;
		}
//根据IP进行过滤
		pmsframefilter_ctt->flag_filter_ip		  =ms_bufUnvalid(pmsframefilter_config->filter_ip) 	 	? ms_false : ms_true;
		pmsframefilter_ctt->flag_filter_ip_source=ms_bufUnvalid(pmsframefilter_config->filter_ip_source) 	? ms_false : ms_true;
		pmsframefilter_ctt->flag_filter_ip_dest	  =ms_bufUnvalid(pmsframefilter_config->filter_ip_dest) 	? ms_false : ms_true;
//根据端口进行过滤
		pmsframefilter_ctt->flag_filter_port		=(pmsframefilter_config->filter_port>0) 	 	? ms_true : ms_false;
		pmsframefilter_ctt->flag_filter_port_source	=(pmsframefilter_config->filter_port_source>0) 	? ms_true : ms_false;
		pmsframefilter_ctt->flag_filter_port_dest	=(pmsframefilter_config->filter_port_dest>0) 	? ms_true : ms_false;
//获取是否设置了过滤规则
		if(ms_false==pmsframefilter_ctt->flag_filter_mac
			&&ms_false==pmsframefilter_ctt->flag_filter_mac_source
			&&ms_false==pmsframefilter_ctt->flag_filter_mac_dest
			&&ms_false==pmsframefilter_ctt->flag_filter_protocol
			&&ms_false==pmsframefilter_ctt->flag_filter_ip
			&&ms_false==pmsframefilter_ctt->flag_filter_ip_source
			&&ms_false==pmsframefilter_ctt->flag_filter_ip_dest
			&&ms_false==pmsframefilter_ctt->flag_filter_port
			&&ms_false==pmsframefilter_ctt->flag_filter_port_source
			&&ms_false==pmsframefilter_ctt->flag_filter_port_dest){
			pmsframefilter_ctt->flag_filter=ms_false;
		}else{
			pmsframefilter_ctt->flag_filter=ms_true;
		}
		pmsframefilter_ctt->flag_init=ms_true;
	}
//未设置了过滤规则，则直接返回过滤完成
	if(ms_false==pmsframefilter_ctt->flag_filter){
		ms_enDbg(DBG_FILTER,"[%s]---------no need to filter",strdes);
		return ms_true;
	}

//解析RAW数据的结构
	ETHERContext *pether_ctt=&pmsframefilter_ctt->ether_ctt;
	pether_ctt->debug=DBG_FILTER_FRAME;

	ms_bool flag_parseEtherInfo=msframe_api_isFilterEtherInfo(pmsframefilter_ctt);
	//无需解析EtherInfo，则直接返回。加快处理速度
	msframe_api_doFrame( pether_ctt,frame_buf,flag_parseEtherInfo);
	if(ms_true==msframe_api_isFilterMac(pmsframefilter_ctt)
		&&ms_false==msframe_innerapi_filterFrameByMac(strdes,pmsframefilter_config)){
		return ms_false;
	}		
	if(ms_true==flag_parseEtherInfo
		&&ms_false==msframe_innerapi_filterFrameByEtherInfo(strdes,pmsframefilter_config)){
		return ms_false;
	}		
	ms_enDbg(DBG_FILTER,"[%s]---------filter ok",strdes);
	return ms_true;
}

ms_s32 msframe_api_buildArp( ETHERContext * ms_out pether_ctt, ms_string str_source_mac, 
	ms_string sender_ipaddr, ms_string target_ipaddr,ms_byte *outbuf )
{
	ms_bufcheckRetDes(0,pether_ctt,"Param error####pether_ctt");
	ms_bufcheckRetDes(0,str_source_mac,"Param error####str_source_mac");
	ms_bufcheckRetDes(0,outbuf,"Param error####outbuf");
	
	ARPHEADERContext *parpheader_ctt=&pether_ctt->ethertype_data.arpheader_ctt;
	FRAMEContext *pframe_ctt=&pether_ctt->frame_ctt;
	msframe_innerapi_buildEthrt(pether_ctt, "FF:FF:FF:FF:FF:FF",str_source_mac, ETHERTYPE_ARP,outbuf);

	parpheader_ctt->hardware_type=ARPHRD_ETHER;
	parpheader_ctt->protocol_type=ETHERTYPE_IP;
	parpheader_ctt->hardware_size= 6;
	parpheader_ctt->protocol_size= 4;
	parpheader_ctt->opcode= ARPOP_REQUEST;
	msnet_api_macStr2Byte( str_source_mac, parpheader_ctt->sender_mac);
	parpheader_ctt->sender_ipaddr=htonl(inet_addr(sender_ipaddr));
	msnet_api_macStr2Byte( "FF:FF:FF:FF:FF:FF", parpheader_ctt->target_mac);
	parpheader_ctt->target_ipaddr=htonl(inet_addr(target_ipaddr));

	ms_network_2b(&outbuf[14], parpheader_ctt->hardware_type);
	ms_network_2b(&outbuf[16], parpheader_ctt->protocol_type);
	outbuf[18]=parpheader_ctt->hardware_size;
	outbuf[19]=parpheader_ctt->protocol_size;
	ms_network_2b(&outbuf[20], parpheader_ctt->opcode);
	ms_memcpy(&outbuf[22], parpheader_ctt->sender_mac,6);
	ms_network_4b(&outbuf[28], parpheader_ctt->sender_ipaddr);
	ms_memcpy(&outbuf[32], parpheader_ctt->target_mac,6);
	ms_network_4b(&outbuf[38], parpheader_ctt->target_ipaddr);
	//ms_bufHexAscii("rtp", &outbuf[14], 28);
	msframe_innerapi_parseArp(pether_ctt, (struct arphdr *)&outbuf[14]);
	return 42;
}


ms_u32 msframe_api_buildTcp(ETHERContext * ms_in pether_ctt,MSBULDTCPContext *pmsbuildtcp_ctt,ms_pbyte ms_out pether_pkt)
{
	ms_bufcheckRetDes(ms_f32,pether_ctt,"Param error####pether_ctt");
	ms_bufcheckRetDes(ms_f32,pether_pkt,"Param error####pether_pkt");
	#define TCPHEADER_LEN	(20/4)

	ms_u32 len=0;
/*ether header*/
	msframe_innerapi_buildEthrt(pether_ctt, pmsbuildtcp_ctt->str_dest_mac,pmsbuildtcp_ctt->str_source_mac, ETHERTYPE_IP,&pether_pkt[len+0]);
	len+=14;
/*ip header*/
	msframe_innerapi_buildIpv4(ms_false,pether_ctt, IPPROTO_TCP,pmsbuildtcp_ctt->source_ip, pmsbuildtcp_ctt->dest_ip, 
		pmsbuildtcp_ctt->opt_ctt.tcpheader_opt_len,&pether_pkt[len+0]);
	IPHEADERContext *pipheader_ctt=&pether_ctt->ethertype_data.ipheader_ctt;
	len+=(pipheader_ctt->header_len*4);
/*tcp header*/
	msframe_innerapi_buildTcpPayload(pether_ctt,pmsbuildtcp_ctt,&pether_pkt[len+0]);
	TCPHEADERContext *ptcpheader_ctt=&pether_ctt->ipprotocol_data.tcpheader_ctt;
	len+=(ptcpheader_ctt->header_len*4+pether_ctt->data_len);
	return len;
}
ms_u32 msframe_api_buildUdp(ETHERContext * ms_in pether_ctt,MSBULDUDPContext *pPUdp_ctt,ms_pbyte ms_out pether_pkt)
{
	ms_bufcheckRetDes(ms_f32,pether_ctt,"Param error####pether_ctt");
	ms_bufcheckRetDes(ms_f32,pether_pkt,"Param error####pether_pkt");
	#define TCPHEADER_LEN	(20/4)

	ms_u32 len=0;
/*ether header*/
	msframe_innerapi_buildEthrt(pether_ctt, pPUdp_ctt->destMac,pPUdp_ctt->srcMac, ETHERTYPE_IP,&pether_pkt[len+0]);
	len+=14;
/*ip header*/
	msframe_innerapi_buildIpv4(ms_false,pether_ctt, IPPROTO_UDP,pPUdp_ctt->srcIp, pPUdp_ctt->destIp, 
		0,&pether_pkt[len+0]);
	IPHEADERContext *pipheader_ctt=&pether_ctt->ethertype_data.ipheader_ctt;
	len+=(pipheader_ctt->header_len*4);
/*tcp header*/
	msframe_innerapi_buildUdpPayload(pether_ctt,pPUdp_ctt,&pether_pkt[len+0]);
	TCPHEADERContext *ptcpheader_ctt=&pether_ctt->ipprotocol_data.tcpheader_ctt;
	len+=(ptcpheader_ctt->header_len*4+8+pether_ctt->data_len);
	return len;
}

ms_u32 msframe_api_buildIgmp(ETHERContext * ms_in pether_ctt,MSBULDIGMPContext *pigmp_ctt_in,ms_bool flag_pppoe,ms_pbyte ms_out pether_pkt)
{
	ms_bufcheckRetDes(ms_f32,pether_ctt,"Param error####pether_ctt");
	ms_bufcheckRetDes(ms_f32,pether_pkt,"Param error####pether_pkt");
	ms_u32 len=0;
/*ether header*/
	if(flag_pppoe){
		/*Link cooked capture*/
		//len+=msframe_innerapi_buildLinuxCooked(ETHERTYPE_IP, &pether_pkt[len+0]);
		len+=msframe_innerapi_buildEthrt(pether_ctt, pigmp_ctt_in->str_dest_mac,pigmp_ctt_in->str_source_mac, 0x8864,&pether_pkt[len+0]);
		pether_pkt[len]=0x11;len+=1;
		pether_pkt[len]=0x00;len+=1;
		ms_network_2b(&pether_pkt[len], 0x0022);len+=2;
		ms_network_2b(&pether_pkt[len], 0x0022);len+=2;
		ms_network_2b(&pether_pkt[len], 0x0021);len+=2;
	}else{
		len+=msframe_innerapi_buildEthrt(pether_ctt, pigmp_ctt_in->str_dest_mac,pigmp_ctt_in->str_source_mac, ETHERTYPE_IP,&pether_pkt[len+0]);
	}
/*ip header*/
	ms_u32 exlen=8;
	switch(pigmp_ctt_in->igmp_ver){
		case IGMP_VERSION_1:
		case IGMP_VERSION_2:
			exlen=8;
			break;
		case IGMP_VERSION_3:
			exlen=16;
			break;
	}
	msframe_innerapi_buildIpv4(flag_pppoe,pether_ctt, IPPROTO_IGMP,pigmp_ctt_in->source_ip, pigmp_ctt_in->dest_ip, 
		exlen,&pether_pkt[len+0]);
	IPHEADERContext *pipheader_ctt=&pether_ctt->ethertype_data.ipheader_ctt;
	len+=(pipheader_ctt->header_len*4);
/*igmp header*/
	ms_u32 igmp_len=msframe_innerapi_buildIgmp(pether_ctt,pigmp_ctt_in,&pether_pkt[len+0]);
	len+=igmp_len;
	return len;
}
ms_bool msframe_api_is_ipArp(ETHERContext * ms_in pether_ctt)
{
	ms_bufcheckRetDes(ms_false,pether_ctt,"Param error####pether_ctt");
	return (  (ETHERTYPE_IP==pether_ctt->frame_ctt.type)
			||(ETHERTYPE_ARP==pether_ctt->frame_ctt.type)
	) ? ms_true : ms_false;
}
ms_bool msframe_api_is_IparpOrIpaddr(ETHERContext * ms_in pether_ctt,
	ms_string ms_in  filter_sourceip,ms_string ms_in  filter_destip)
{
	ms_bufcheckRetDes(ms_false,pether_ctt,"Param error####pether_ctt");
	ms_bool ret=ms_false;
	IPHEADERContext *pipheader_ctt=&pether_ctt->ethertype_data.ipheader_ctt;
	ARPHEADERContext *parpheader_ctt=&pether_ctt->ethertype_data.arpheader_ctt;
	switch(pether_ctt->frame_ctt.type){
		case ETHERTYPE_IP:
			ret=((htonl(inet_addr(filter_sourceip)==pipheader_ctt->source_ip))
					||(htonl(inet_addr(filter_destip)==pipheader_ctt->dest_ip))
				) ? ms_true: ms_false;
			break;
			
		case ETHERTYPE_ARP:
			ret=(((inet_addr(filter_sourceip)==parpheader_ctt->sender_ipaddr))
					||((inet_addr(filter_destip)==parpheader_ctt->target_ipaddr))
				) ? ms_true: ms_false;
			break;
		default:
			ret=ms_false;
			break;
	}
	return ret;
}
ms_bool msframe_api_isTcp_dTos_ack(ETHERContext * ms_in pether_ctt,ms_string ms_in  filter_destip)
{
	ms_bufcheckRetDes(ms_false,pether_ctt,"Param error####pether_ctt");
	ms_bufcheckRetDes(ms_false,filter_destip,"Param error####filter_destip");
	IPHEADERContext *pipheader_ctt=&pether_ctt->ethertype_data.ipheader_ctt;
	TCPHEADERContext *ptcpheader_ctt=&pether_ctt->ipprotocol_data.tcpheader_ctt;
	return (    (ETHERTYPE_IP==pether_ctt->frame_ctt.type)
			&&(IPPROTO_TCP==pipheader_ctt->protocol)
			&&(htonl(inet_addr(filter_destip)==pipheader_ctt->dest_ip))	
			&&((1==ptcpheader_ctt->ack)
				&&(0==ptcpheader_ctt->urg)
				&&(0==ptcpheader_ctt->psh)
				&&(0==ptcpheader_ctt->rst)
				&&(0==ptcpheader_ctt->syn)
				&&(0==ptcpheader_ctt->fin)
				&&(pether_ctt->data_len==0) )
	) ? ms_true : ms_false;
}

ms_bool msframe_api_isTcp_dTos_close(ETHERContext * ms_in pether_ctt,ms_string ms_in  filter_destip)
{
	ms_bufcheckRetDes(ms_false,pether_ctt,"Param error####pether_ctt");
	ms_bufcheckRetDes(ms_false,filter_destip,"Param error####filter_destip");
	IPHEADERContext *pipheader_ctt=&pether_ctt->ethertype_data.ipheader_ctt;
	TCPHEADERContext *ptcpheader_ctt=&pether_ctt->ipprotocol_data.tcpheader_ctt;
	return (    (ETHERTYPE_IP==pether_ctt->frame_ctt.type)
			&&(IPPROTO_TCP==pipheader_ctt->protocol)
			&&(htonl(inet_addr(filter_destip)==pipheader_ctt->dest_ip))	
			&&((1==ptcpheader_ctt->ack)
				&&(0==ptcpheader_ctt->urg)
				&&(0==ptcpheader_ctt->psh)
				&&(0==ptcpheader_ctt->rst)
				&&(0==ptcpheader_ctt->syn)
				&&(1==ptcpheader_ctt->fin)	)
	) ? ms_true : ms_false;
}

ms_bool msframe_api_isTcp_sTod_data(ETHERContext * ms_in pether_ctt,ms_string ms_in  filter_srcip)
{
	ms_bufcheckRetDes(ms_false,pether_ctt,"Param error####pether_ctt");
	ms_bufcheckRetDes(ms_false,filter_srcip,"Param error####filter_srcip");
	IPHEADERContext *pipheader_ctt=&pether_ctt->ethertype_data.ipheader_ctt;
	 return ( (ETHERTYPE_IP==pether_ctt->frame_ctt.type)
			&&(IPPROTO_TCP==pipheader_ctt->protocol)
			&&(htonl(inet_addr(filter_srcip)==pipheader_ctt->source_ip))	
			&&(pether_ctt->data_len>0)
	) ? ms_true : ms_false;
}

ms_bool msframe_api_isTcp(ETHERContext * ms_in pether_ctt)
{
	ms_bufcheckRetDes(ms_false,pether_ctt,"Param error####pether_ctt");
	IPHEADERContext *pipheader_ctt=&pether_ctt->ethertype_data.ipheader_ctt;
	 return (    (ETHERTYPE_IP==pether_ctt->frame_ctt.type)
			&&(IPPROTO_TCP==pipheader_ctt->protocol)	
	) ? ms_true : ms_false;
}

ms_u16 msframe_api_tcpChecksum(ETHERContext * ms_in pether_ctt,ms_pbyte ms_in  pether_pkt)	
{
	ms_bufcheckRetDes(ms_f16,pether_ctt,"Param error####pether_ctt");
	ms_bufcheckRetDes(ms_f16,pether_pkt,"Param error####pether_pkt");
	FRAMEContext *pframe_ctt=&pether_ctt->frame_ctt;
	IPHEADERContext *pipheader_ctt=&pether_ctt->ethertype_data.ipheader_ctt;
	TCPHEADERContext *ptcpheader_ctt=&pether_ctt->ipprotocol_data.tcpheader_ctt;
	ms_byte tcpcheck_buf[2048]={0};
	/*----extern  header----*/
	//source_ip
	ms_network_4b(&(tcpcheck_buf[0]), pipheader_ctt->source_ip);
	//dest_ip
	ms_network_4b(&(tcpcheck_buf[4]), pipheader_ctt->dest_ip);
	//0
	tcpcheck_buf[8]=0;
	//protocol
	tcpcheck_buf[9]=pipheader_ctt->protocol;
	//len
	ms_network_2b(&(tcpcheck_buf[10]), (ptcpheader_ctt->header_len*4+pether_ctt->data_len));
	
	/*header*/
	ms_memcpy(&tcpcheck_buf[12], pether_pkt, ptcpheader_ctt->header_len*4);
	/*data*/
	ms_memcpy(&tcpcheck_buf[12+ptcpheader_ctt->header_len*4], pether_ctt->data, pether_ctt->data_len);
	return msnet_api_checksum((ms_u16 * )tcpcheck_buf, 12+ptcpheader_ctt->header_len*4+pether_ctt->data_len);	
}
ms_u16 msframe_api_udpChecksum(ETHERContext * ms_in pether_ctt,ms_pbyte ms_in  pether_pkt)	
{
	ms_bufcheckRetDes(ms_f16,pether_ctt,"Param error####pether_ctt");
	ms_bufcheckRetDes(ms_f16,pether_pkt,"Param error####pether_pkt");
	FRAMEContext *pframe_ctt=&pether_ctt->frame_ctt;
	IPHEADERContext *pipheader_ctt=&pether_ctt->ethertype_data.ipheader_ctt;
	UDPHEADERContext *pHUdp_ctt=&pether_ctt->ipprotocol_data.udpheader_ctt;

	ms_byte tcpcheck_buf[2048]={0};
	/*----extern  header----*/
	//source_ip
	ms_network_2b(&(tcpcheck_buf[0]), (pipheader_ctt->source_ip&0xFFFF));
	ms_network_2b(&(tcpcheck_buf[2]), ((pipheader_ctt->source_ip>>16)&0xFFFF));
	//dest_ip
	ms_network_2b(&(tcpcheck_buf[4]), (pipheader_ctt->dest_ip&0xFFFF));
	ms_network_2b(&(tcpcheck_buf[6]), ((pipheader_ctt->dest_ip>>16)&0xFFFF));

	//protocol
	tcpcheck_buf[8]=pipheader_ctt->protocol&0xFF;
	tcpcheck_buf[9]=pipheader_ctt->protocol>>8&0xFF;

	//len
	tcpcheck_buf[10]=(8+pether_ctt->data_len)&0xFF;
	tcpcheck_buf[11]=(8+pether_ctt->data_len)>>8&0xFF;

	/*header*/
	tcpcheck_buf[12]=pHUdp_ctt->source_port&0xFF;
	tcpcheck_buf[13]=pHUdp_ctt->source_port>>8&0xFF;
	tcpcheck_buf[14]=pHUdp_ctt->dest_port&0xFF;
	tcpcheck_buf[15]=pHUdp_ctt->dest_port>>8&0xFF;
	tcpcheck_buf[16]=pHUdp_ctt->len&0xFF;
	tcpcheck_buf[17]=pHUdp_ctt->len>>8&0xFF;
	tcpcheck_buf[18]=pHUdp_ctt->check_sum&0xFF;
	tcpcheck_buf[19]=pHUdp_ctt->check_sum>>8&0xFF;
	
	/*data*/
	ms_s32 dataLen=pether_ctt->data_len%2 ? (pether_ctt->data_len+1) : pether_ctt->data_len;
	for(ms_s32 data_index=0;data_index<dataLen;data_index+=2){
		tcpcheck_buf[20+data_index]=pether_ctt->data[data_index+1];
		tcpcheck_buf[20+data_index+1]=pether_ctt->data[data_index];
	}
	return msnet_api_checksumUdp((ms_u16 * )tcpcheck_buf, (12+8+dataLen));	
}

ms_u32 msframe_api_buildTcpAck(ETHERContext * ms_in pether_ctt,ms_pbyte ms_in  pether_pkt)	
{
	ms_bufcheckRetDes(ms_f32,pether_ctt,"Param error####pether_ctt");
	ms_bufcheckRetDes(ms_f32,pether_pkt,"Param error####pether_pkt");
	FRAMEContext *pframe_ctt=&pether_ctt->frame_ctt;
	IPHEADERContext *pipheader_ctt=&pether_ctt->ethertype_data.ipheader_ctt;
	TCPHEADERContext *ptcpheader_ctt=&pether_ctt->ipprotocol_data.tcpheader_ctt;
	#define TCPHEADER_LEN	(20/4)
/*ether header*/
	ms_bufSwitch((ms_pbyte)pframe_ctt->dest_mac, (ms_pbyte)pframe_ctt->source_mac, sizeof(pframe_ctt->source_mac));
	pframe_ctt->type=0x0800;	//ip
/*ip header*/
	pipheader_ctt->version=0x4;
	pipheader_ctt->header_len=0x5;
	pipheader_ctt->id+=300;
	pipheader_ctt->tos=0x00;
	/*Fragment use:id,flags,frag_offset*/
	pipheader_ctt->flags=0x2;
	pipheader_ctt->checksum=0x0000;
	pipheader_ctt->protocol=6;	//tcp
	pipheader_ctt->source_ip=htonl(pipheader_ctt->source_ip);
	pipheader_ctt->dest_ip=htonl(pipheader_ctt->dest_ip);
	ms_bufSwitch((ms_pbyte)&pipheader_ctt->source_ip, (ms_pbyte)&pipheader_ctt->dest_ip, sizeof(pipheader_ctt->dest_ip));
	pipheader_ctt->total_len=(ms_u16) ((pipheader_ctt->header_len*4+TCPHEADER_LEN*4)&0xffff);
/*tcp header*/
	ms_bufSwitch((ms_pbyte)&ptcpheader_ctt->source_port, (ms_pbyte)&ptcpheader_ctt->dest_port, sizeof(ptcpheader_ctt->dest_port));
	ms_bufSwitch((ms_pbyte)&ptcpheader_ctt->seq_num,(ms_pbyte)&ptcpheader_ctt->ack_num, sizeof(ptcpheader_ctt->ack_num));
	ptcpheader_ctt->ack_num+=pether_ctt->data_len;
	ptcpheader_ctt->win_size=65535;
	ptcpheader_ctt->check_sum=0x0000;	
	ptcpheader_ctt->urgen_pointer=0x0000;
	ptcpheader_ctt->header_len=TCPHEADER_LEN;
	ptcpheader_ctt->urg=0;
	ptcpheader_ctt->ack=1;
	ptcpheader_ctt->psh=0;
	ptcpheader_ctt->rst=0;
	ptcpheader_ctt->syn=0;
	ptcpheader_ctt->fin=0;
/*data header*/
	pether_ctt->data_len=0;
//frame_ctt		
	ms_u32 len=0;
	ms_memcpy(&pether_pkt[len+0], pframe_ctt->dest_mac, 6);
	ms_memcpy(&pether_pkt[len+6], pframe_ctt->source_mac, 6);
	ms_network_2b(&(pether_pkt[len+12]), pframe_ctt->type);
	len+=14;
//ipheader_ctt
	pether_pkt[len+0]=pipheader_ctt->version<<4|pipheader_ctt->header_len;
	pether_pkt[len+1]=pipheader_ctt->tos;
	ms_network_2b(&(pether_pkt[len+2]), pipheader_ctt->total_len);
	ms_network_2b(&(pether_pkt[len+4]), pipheader_ctt->id);
	pether_pkt[len+6]=pipheader_ctt->flags<<5|(pipheader_ctt->frag_offset&0x1f00)>>8;
	pether_pkt[len+7]=pipheader_ctt->frag_offset&0xff;
	pether_pkt[len+8]=pipheader_ctt->ttl;
	pether_pkt[len+9]=pipheader_ctt->protocol;
	ms_network_2b(&(pether_pkt[len+10]), 00);
	ms_network_4b(&(pether_pkt[len+12]), pipheader_ctt->source_ip);
	ms_network_4b(&(pether_pkt[len+16]), pipheader_ctt->dest_ip);
	pipheader_ctt->checksum=msnet_api_checksum((ms_u16 * )&pether_pkt[len+0], 20);
	ms_network_2b(&(pether_pkt[len+10]), pipheader_ctt->checksum);
	len+=20;
//tcpheader_ctt
	ms_network_2b(&(pether_pkt[len+0]), ptcpheader_ctt->source_port);
	ms_network_2b(&(pether_pkt[len+2]), ptcpheader_ctt->dest_port);
	ms_network_4b(&(pether_pkt[len+4]), ptcpheader_ctt->seq_num);
	ms_network_4b(&(pether_pkt[len+8]), ptcpheader_ctt->ack_num);
	pether_pkt[len+12]=ptcpheader_ctt->header_len<<4|(ptcpheader_ctt->res&0x3c)>>2;	
	pether_pkt[len+13]=(ptcpheader_ctt->res&0x3)<<6|ptcpheader_ctt->urg<<5|ptcpheader_ctt->ack<<4|ptcpheader_ctt->psh<<3 \
		|ptcpheader_ctt->rst<<2|ptcpheader_ctt->syn<<1|ptcpheader_ctt->fin;	
	ms_network_2b(&(pether_pkt[len+14]), ptcpheader_ctt->win_size);
	ms_network_2b(&(pether_pkt[len+16]), ptcpheader_ctt->check_sum);
	ms_network_2b(&(pether_pkt[len+18]), ptcpheader_ctt->urgen_pointer);

	ptcpheader_ctt->check_sum=msframe_api_tcpChecksum(pether_ctt,&pether_pkt[len+0]);	
	ms_network_2b(&(pether_pkt[len+16]), ptcpheader_ctt->check_sum);
	len+=ptcpheader_ctt->header_len*4;
	return len;
}

ms_u32 msframe_api_buildTcpData(ETHERContext * ms_in pether_ctt,ms_pbyte ms_in pether_pkt)	
{
	ms_bufcheckRetDes(ms_f32,pether_ctt,"Param error####pether_ctt");
	ms_bufcheckRetDes(ms_f32,pether_pkt,"Param error####pether_pkt");
	FRAMEContext *pframe_ctt=&pether_ctt->frame_ctt;
	IPHEADERContext *pipheader_ctt=&pether_ctt->ethertype_data.ipheader_ctt;
	TCPHEADERContext *ptcpheader_ctt=&pether_ctt->ipprotocol_data.tcpheader_ctt;
/*ether header*/
	pframe_ctt->type=0x0800;	//ip
/*ip header*/
	pipheader_ctt->version=0x4;
	pipheader_ctt->header_len=0x5;
	pipheader_ctt->id+=300;
	pipheader_ctt->tos=0x00;
	/*Fragment use:id,flags,frag_offset*/
	pipheader_ctt->flags=0x2;
	pipheader_ctt->checksum=0x0000;
	pipheader_ctt->protocol=6;	//tcp
	ms_u32  source_ip=pipheader_ctt->source_ip;
	ms_u32  dest_ip=pipheader_ctt->dest_ip;
	pipheader_ctt->source_ip=htonl(dest_ip);
	pipheader_ctt->dest_ip=htonl(source_ip);
	ms_bufSwitch((ms_pbyte)&pipheader_ctt->source_ip, (ms_pbyte)&pipheader_ctt->dest_ip, sizeof(pipheader_ctt->dest_ip));
	pipheader_ctt->total_len=(ms_u16) ((pipheader_ctt->header_len*4+TCPHEADER_LEN*4+pether_ctt->data_len)&0xffff);
/*tcp header*/
	ptcpheader_ctt->win_size=65535;
	ptcpheader_ctt->check_sum=0x0000;	
	ptcpheader_ctt->urgen_pointer=0x0000;
	ptcpheader_ctt->header_len=TCPHEADER_LEN;
/*data header*/

//frame_ctt		
	ms_u32 len=0;
	ms_memcpy(&pether_pkt[len+0], pframe_ctt->dest_mac, 6);
	ms_memcpy(&pether_pkt[len+6], pframe_ctt->source_mac, 6);
	ms_network_2b(&(pether_pkt[len+12]), pframe_ctt->type);
	len+=14;
//ipheader_ctt
	pether_pkt[len+0]=pipheader_ctt->version<<4|pipheader_ctt->header_len;
	pether_pkt[len+1]=pipheader_ctt->tos;
	ms_network_2b(&(pether_pkt[len+2]), pipheader_ctt->total_len);
	ms_network_2b(&(pether_pkt[len+4]), pipheader_ctt->id);
	pether_pkt[len+6]=pipheader_ctt->flags<<5|(pipheader_ctt->frag_offset&0x1f00)>>8;
	pether_pkt[len+7]=pipheader_ctt->frag_offset&0xff;
	pether_pkt[len+8]=pipheader_ctt->ttl;
	pether_pkt[len+9]=pipheader_ctt->protocol;
	ms_network_2b(&(pether_pkt[len+10]), 00);
	ms_network_4b(&(pether_pkt[len+12]), pipheader_ctt->source_ip);
	ms_network_4b(&(pether_pkt[len+16]), pipheader_ctt->dest_ip);
	pipheader_ctt->checksum=msnet_api_checksum((ms_pu16 )&pether_pkt[len+0], 20);
	ms_network_2b(&(pether_pkt[len+10]), pipheader_ctt->checksum);
	len+=20;
//tcpheader_ctt
	ms_network_2b(&(pether_pkt[len+0]), ptcpheader_ctt->source_port);
	ms_network_2b(&(pether_pkt[len+2]), ptcpheader_ctt->dest_port);
	ms_network_4b(&(pether_pkt[len+4]), ptcpheader_ctt->seq_num);
	ms_network_4b(&(pether_pkt[len+8]), ptcpheader_ctt->ack_num);
	pether_pkt[len+12]=ptcpheader_ctt->header_len<<4|(ptcpheader_ctt->res&0x3c)>>2;	
	pether_pkt[len+13]=(ptcpheader_ctt->res&0x3)<<6|ptcpheader_ctt->urg<<5|ptcpheader_ctt->ack<<4|ptcpheader_ctt->psh<<3 \
		|ptcpheader_ctt->rst<<2|ptcpheader_ctt->syn<<1|ptcpheader_ctt->fin;	
	ms_network_2b(&(pether_pkt[len+14]), ptcpheader_ctt->win_size);
	ms_network_2b(&(pether_pkt[len+16]), ptcpheader_ctt->check_sum);
	ms_network_2b(&(pether_pkt[len+18]), ptcpheader_ctt->urgen_pointer);

	ptcpheader_ctt->check_sum=msframe_api_tcpChecksum(pether_ctt,&pether_pkt[len+0]);	
	ms_network_2b(&(pether_pkt[len+16]), ptcpheader_ctt->check_sum);
	len+=ptcpheader_ctt->header_len*4+pether_ctt->data_len;
	return len;
}
#undef MSNETFRAME_C
